package logging

import (
	"fmt"
	"log"
	"os"
	"pids-cloud-server/config"
	"strings"
	"time"

	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

var logger *zap.Logger

func init() {
	logcfg := config.LogCfg
	log.Printf("打印出日志配置参数logcfg: %+v", logcfg)
	// 配置日志滚动
	cachedLogger := NewCachedLogger(logcfg.BasePath, logcfg.MaxSize, logcfg.MaxBackup, logcfg.MaxAge, logcfg.Compress)

	// 解析配置的日志级别
	logLevel := parseLogLevel(logcfg.Level)

	encoderConfig := zapcore.EncoderConfig{
		TimeKey:       "time",
		LevelKey:      "level",
		NameKey:       "logger",
		CallerKey:     "caller",
		FunctionKey:   zapcore.OmitKey,
		MessageKey:    "msg",
		StacktraceKey: "stacktrace",
		LineEnding:    zapcore.DefaultLineEnding,
		EncodeLevel:   zapcore.CapitalLevelEncoder, // 使用大写级别
		EncodeTime: func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
			// 自定义时间格式
			enc.AppendString(t.Format("2006-01-02 15:04:05.000"))
		},
		EncodeDuration: zapcore.SecondsDurationEncoder,
		EncodeCaller:   zapcore.ShortCallerEncoder,
	}

	// 创建控制台输出
	consoleEncoder := zapcore.NewConsoleEncoder(encoderConfig)
	consoleWriter := zapcore.AddSync(os.Stdout)

	// 创建文件输出 - 根据级别分别写入不同文件
	debugFile := zapcore.AddSync(cachedLogger.DebugLogger)
	infoFile := zapcore.AddSync(cachedLogger.InfoLogger)
	warnFile := zapcore.AddSync(cachedLogger.WarnLogger)
	errorFile := zapcore.AddSync(cachedLogger.ErrorLogger)

	// 创建统一的日志级别控制
	enabler := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
		return lvl >= logLevel
	})

	// 为不同级别的日志创建独立的core，但都使用统一的级别控制
	cores := []zapcore.Core{
		// 控制台输出 - 统一级别控制
		zapcore.NewCore(consoleEncoder, consoleWriter, enabler),
	}

	// 文件输出 - 按级别分文件，但仍受全局级别控制
	if logLevel <= zapcore.DebugLevel {
		debugEnabler := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
			return lvl == zapcore.DebugLevel && lvl >= logLevel
		})
		cores = append(cores, zapcore.NewCore(consoleEncoder, debugFile, debugEnabler))
	}

	if logLevel <= zapcore.InfoLevel {
		infoEnabler := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
			return lvl == zapcore.InfoLevel && lvl >= logLevel
		})
		cores = append(cores, zapcore.NewCore(consoleEncoder, infoFile, infoEnabler))
	}

	if logLevel <= zapcore.WarnLevel {
		warnEnabler := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
			return lvl == zapcore.WarnLevel && lvl >= logLevel
		})
		cores = append(cores, zapcore.NewCore(consoleEncoder, warnFile, warnEnabler))
	}

	if logLevel <= zapcore.ErrorLevel {
		errorEnabler := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
			return lvl == zapcore.ErrorLevel && lvl >= logLevel
		})
		cores = append(cores, zapcore.NewCore(consoleEncoder, errorFile, errorEnabler))
	}

	core := zapcore.NewTee(cores...)

	logger := zap.New(core)
	// 确保日志缓冲区被写入
	defer logger.Sync()
	// 设置全局日志记录器
	zap.ReplaceGlobals(logger)

	InitLogger(logger)
}

// parseLogLevel 解析字符串日志级别为 zapcore.Level
func parseLogLevel(level string) zapcore.Level {
	switch strings.ToLower(level) {
	case "debug":
		return zapcore.DebugLevel
	case "info":
		return zapcore.InfoLevel
	case "warn", "warning":
		return zapcore.WarnLevel
	case "error":
		return zapcore.ErrorLevel
	case "fatal":
		return zapcore.FatalLevel
	default:
		// 默认为 info 级别
		return zapcore.InfoLevel
	}
}

func InitLogger(l *zap.Logger) {
	logger = l
}

func Info(args ...interface{}) {
	if logger != nil {
		logger.Info(fmt.Sprint(args...))
	}
}

func Error(args ...interface{}) {
	if logger != nil {
		logger.Error(fmt.Sprint(args...))
	}
}

func Debug(args ...interface{}) {
	if logger != nil {
		logger.Debug(fmt.Sprint(args...))
	}
}

func Fatal(args ...interface{}) {
	if logger != nil {
		logger.Fatal(fmt.Sprint(args...))
	}
}
func Warn(args ...interface{}) {
	if logger != nil {
		logger.Warn(fmt.Sprint(args...))
	}
}

// 新增支持格式化的日志方法
func Infof(format string, args ...interface{}) {
	if logger != nil {
		logger.Info(fmt.Sprintf(format, args...))
	}
}

func Errorf(format string, args ...interface{}) {
	if logger != nil {
		logger.Error(fmt.Sprintf(format, args...))
	}
}

func Debugf(format string, args ...interface{}) {
	if logger != nil {
		logger.Debug(fmt.Sprintf(format, args...))
	}
}

func Fatalf(format string, args ...interface{}) {
	if logger != nil {
		logger.Fatal(fmt.Sprintf(format, args...))
	}
}

func Warnf(format string, args ...interface{}) {
	if logger != nil {
		logger.Warn(fmt.Sprintf(format, args...))
	}
}
